<?php

namespace App\Http\Controllers\Api\Orders;

use App\Http\Controllers\Controller;
use App\Http\Requests\Plane\Order\PlaneChangeApplyRequest;
use App\Http\Requests\Train\Order\RequiredOrderSnRequest;
use App\Http\Resources\Plane\PlaneOrder\BeforeRefundPassengerResource;
use App\Http\Resources\Plane\PlaneOrder\PlaneOrderResource;
use App\Http\Resources\Train\TrainOrder\PriceDetailsResource;
use App\Jobs\Plane\PlaneOrder\ProcessRefundApply;
use App\Models\Orders\Repositories\Interfaces\OrdersRepositoryInterface;
use App\Models\Plane\PlaneOrderPassengers\Repositories\Interfaces\PlaneOrderPassengerRepositoryInterface;
use App\Models\Plane\PlaneOrders\PlaneOrder;
use App\Models\Plane\PlaneOrders\PlaneOrderReturnApply;
use App\Models\Plane\PlaneOrders\Repositories\Interfaces\PlaneOrderRepositoryInterface;
use App\Trip\Enums\Plane\PlaneProviders;
use App\Trip\Orders\BookOrders\BookOrdersManager;
use App\Trip\Orders\TripOrderState;
use App\Trip\Passengers\OrderSubPassenger;
use App\Trip\Plane\OrderSelectedPassengers;
use App\Trip\Plane\Providers\Qunar\Qunar;
use App\Trip\Plane\Requests\RulesRequest;
use App\Trip\Plane\Wrappers\ChangeFlightsResultWrapper;
use App\Trip\Plane\Wrappers\MoreRulesResultWrapper;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Throwable;

class PlaneOrdersController extends Controller
{
    public PlaneOrderPassengerRepositoryInterface $orderPassengerRepo;
    private string|int|null                       $user_id;
    private PlaneOrderRepositoryInterface         $planeOrderRepo;
    private OrdersRepositoryInterface             $orderRepo;

    public function __construct(
        PlaneOrderRepositoryInterface          $planeOrderRepository,
        OrdersRepositoryInterface              $commonOrderRepository,
        PlaneOrderPassengerRepositoryInterface $orderPassengerRepository
    )
    {
        $this->planeOrderRepo     = $planeOrderRepository;
        $this->orderRepo          = $commonOrderRepository;
        $this->orderPassengerRepo = $orderPassengerRepository;
        $this->user_id            = auth()->id();
    }

    public function book(Request $request)
    {

        // 流程 api ->check -> 预定占座 -> 在本系统下单(生成单号) -> 支付 | 或超时取消  -> 已支付(支付需要先用api 校验) ->api 支付
        // 需要现在系统内下单
        $orderData            = $request->all();
        $orderData['user_id'] = $this->user_id;
        Log::info(json_encode(['method' => '飞机订票', 'request' => $request->all()], JSON_UNESCAPED_UNICODE));
        $order_manager = new BookOrdersManager($orderData);
        $orders        = $order_manager->plane_book();
        $orderInfoData = $this->planeOrderRepo->getOrderShowInfoDatasByPlaneOrder($orders['order_info']);
        return $this->success('', $orderInfoData);
    }

    public function plane_orders(Request $request)
    {
        $params            = $request->only([
            'sort_key',
            'sort_value',
            'is_valid',
        ]);
        $params['user_id'] = $this->user_id;
//        Log::info(json_encode(['method' => '飞机票订单列表', 'request' => $request->all()], JSON_UNESCAPED_UNICODE));
        $res = $this->planeOrderRepo->lists($params, $request->input('page_size', 5));


        $request->offsetSet('business', 'train_order_list');
        $res['orders'] = PlaneOrderResource::collection($res['orders']);
        return $this->success('', $res);
    }

    /**
     * 订单详情
     */
    public function order_info(Request $request)
    {

        $error_msg  = "";
        $order_info = $this->planeOrderRepo->getOrderInfo($request->input('order_sn'));
        if (!$order_info || !Gate::allows('order-access', $order_info)) {
            return $this->error(404, "订单不存在");
        }

        $orderInfoData = $this->planeOrderRepo->getOrderShowInfoDatasByPlaneOrder($order_info);

        $qu = new Qunar();
//        $pay = $qu->changePay('mxu230117121431656', [
//            "gqId"         => '29108207',
//            "passengerIds" => '2165707',
//            "totalAmount"  => "200",
//        ]);
//        $pay = $qu->changeQuery('xep230203124335595', '2023-03-03', []);
//        dd($pay);
//        $detail              = $qu->order_detail($order_info, 'xep230203124335595');
//        $orderInfoData['qu'] = $detail->getPassengers();

        return $this->success($error_msg, $orderInfoData);
    }


    /**
     *
     */
    public function refund(RequiredOrderSnRequest $request)
    {
        $order_info = $this->planeOrderRepo->getOrderInfo($request->input('order_sn', ''));
        if (!$order_info || !Gate::allows('order-access', $order_info)) {
            return $this->error(404, "订单不存在");
        }
        $refund_type         = $request->input('refund_type');
        $op                  = new OrderSelectedPassengers($order_info, $request->input('passengers'));
        $passengers          = $op->getSelectedPassengers();
        $sub_out_order_ids   = $op->getSubOutOrderIds();
        $sub_out_order_id    = count($sub_out_order_ids) > 1 ? '' : $sub_out_order_ids[0];
        $service             = $order_info->getPlaneProvider()->getPlaneOrderStrategy();
        $before_query_result = $service->before_refund_reasons($order_info, $passengers);
        $return              = new PlaneOrderReturnApply();
        $return_info         = $return->add($order_info, [
            "user_id"          => $this->user_id,
            "order_sn"         => $order_info->getOrderSn(),
            "return_type"      => $refund_type,
            "out_order_id"     => $order_info->getOutOrderId(),
            "sub_out_order_id" => $sub_out_order_id,
            "out_order_sn"     => $order_info->getOutOrderSn(),
            "passengers"       => $passengers,
            "query_result"     => $before_query_result,
        ]);

        // 这里可以走异步
        // 仅自愿退款  发起
        $msg = "非自愿退票申请成功";
        if ($return_info->getReturnType() == 1) {
            $msg = "自愿退票申请成功";
            ProcessRefundApply::dispatch($service, $order_info, $return_info, $passengers);
        }

        return $this->success($msg, $return_info->toArray());
    }

    public function refund_info(RequiredOrderSnRequest $request)
    {
        $refund     = [];
        $order_info = $this->planeOrderRepo->getOrderInfo($request->input('order_sn'));
        if (!$order_info || !Gate::allows('order-access', $order_info)) {
            return $this->error(404, "订单不存在");
        }

        $return = PlaneOrderReturnApply::where('order_sn', $order_info->getOrderSn())->get();
        return $this->success('', compact('return'));
    }

    /**
     * 改签后退款 需要 输出选中乘客 原订单支付数据 + 新改订单的支付数据
     * @throws Exception
     */
    public function before_refund(Request $request)
    {
        $order_info = $this->planeOrderRepo->getOrderInfo($request->input('order_sn'));
        if (!$order_info || !Gate::allows('order-access', $order_info)) {
            return $this->error(404, "订单不存在");
        }
        $service     = $order_info->QueryStrategy();
        $flight_info = $order_info->getFlightInfo();
        // 验证乘客类型
        $passenger_types = collect($order_info->passengers)->pluck('ticket_price', 'passenger_type')->unique()->toArray();
        $rules           = [];
        $price_map       = [
            1 => 'adult_price',
            3 => 'child_price',
        ];
        // 这里按照乘客类型 查询, 目前任务 同类型的参数一样
        foreach ($passenger_types as $passengerType => $ticket_price) {
            if (!isset($rules[$passengerType])) {
                $rules[$passengerType] = $service->rules(new RulesRequest([
                    'depart_date'       => $order_info->getTripDate(),
                    'flight_no'         => $flight_info->getFlightNo(),
                    'cabin'             => $flight_info->cabin,
                    'carrier_code'      => $flight_info->getFlightNo(),
                    'policy_id'         => $flight_info['provider_policy_id'],
                    'passenger_type'    => $passengerType,
                    'check_prices'      => [
                        $price_map[$passengerType] => $ticket_price,
                    ],
                    'rule_type'         => 1, // 1 退款规则 2 改签规则 4 行李规则 (3:退改,7:退改行李)
                    'order_info'        => $order_info,
                    'passengers'        => $order_info->passengers,
                    'sub_out_order_ids' => collect($order_info->passengers)
                        ->whereIn('order_state', [TripOrderState::ORDER_STATE_TICKETED, TripOrderState::ORDER_STATE_CHANGED])
                        ->pluck('sub_out_order_id')
                        ->unique()->toArray()
                    ,
                ]))->toArray()['refund'];
            }
        }
        $curren_rule = (new MoreRulesResultWrapper($rules))->getCurrentRulePrice();
        return $this->success('', [
            'rules'        => $curren_rule,
            'passengers'   => BeforeRefundPassengerResource::collection(
                $order_info->getPassengersToShow()
                           ->map(fn($passenger) => collect($passenger)->only([
                               'passenger_id',
                               'truename',
                               'sequence',
                               'can_refund',
                               'ticket_price',
                               'fuel_fee',
                               'construct_fee',
                               'mobile',
                               'identity_code',
                               'identity_type',
                               'passenger_type',
                           ]))),
            'refund_types' => $order_info->refund_types(),
        ]);
    }


    /**
     * @throws Exception
     */
    public function before_change(Request $request)
    {
        $order_sn    = $request->input('order_sn');
        $change_date = $request->input('change_date');
        $passengers  = $request->input('passengers');
        $order_info  = $this->planeOrderRepo->getOrderInfo($order_sn);
        if (!$order_info || !Gate::allows('order-access', $order_info)) {
            return $this->error(404, "订单不存在");
        }

        // 查询供应商
        $plane_provider = PlaneProviders::from($order_info->getOrderService());
        $service        = $plane_provider->getPlaneOrderStrategy();
        // 查询可变更的航班
        $flights          = $service->before_change_flights($order_info, $change_date, $passengers);
        $order_passengers = $order_info->getPassengersToShow()->filter(function ($passenger) use ($passengers) {
            // 兼容 passenger_id + sequence
            $passenger_ids = collect($passengers)->map(function ($passenger) {
                if (Str::contains($passenger['passenger_id'], '_')) {
                    return $passenger['passenger_id'];
                } else {
                    return OrderSubPassenger::buildSubPassengerId($passenger['passenger_id'], $passenger['sequence']);
                }
            })->toArray();
            return in_array(OrderSubPassenger::buildSubPassengerId($passenger['passenger_id'], $passenger['sequence']), $passenger_ids);
        });
        // 包装航班的分页排序
        $wrapper = new ChangeFlightsResultWrapper($flights, $request);
        return $this->success('', [
            'passengers' => $order_passengers->map(fn($passenger) => collect($passenger)->only([
                'passenger_id',
                'truename',
                'can_change',
                'mobile',
                'sequence',
                'identity_code',
                'identity_type',
                'passenger_type',
            ])),
            'rules'      => '',
            'flights'    => $wrapper->getFlights(),
            'total'      => $wrapper->getTotal(),
            'page'       => $wrapper->getPage(),
            'last_page'  => $wrapper->getPageSize(),
        ]);
    }

    /**
     * 取消订单
     *
     * @param RequiredOrderSnRequest $request
     *
     */
    public function cancel(RequiredOrderSnRequest $request)
    {
        $order_info = $this->planeOrderRepo->getOrderInfo($request->input('order_sn'));
        if (!$order_info || !Gate::allows('order-access', $order_info)) {
            return $this->error(404, "订单不存在");
        }
        Log::info(json_encode(['method' => '取消订单', 'request' => $request->all()], JSON_UNESCAPED_UNICODE));
        $res = $this->planeOrderRepo->cancelOrder($order_info, $manual = true);
        if ($res) {
            return $this->success("success");
        }
        return $this->error(1, "出票结果确认中，暂无法取消，请稍后");

    }

    public function delete(RequiredOrderSnRequest $request)
    {
        $order_info = $this->orderRepo->getOrderInfo($request->input('order_sn'));
        if (!$order_info || !Gate::allows('order-access', $order_info)) {
            return $this->error(404, "订单不存在");
        }
        $this->orderRepo->destroy($order_info);

        return $this->success("success");

    }


    /**
     * @throws GuzzleException
     * @throws Throwable
     */
    public function change_apply(PlaneChangeApplyRequest $request)
    {
        $order_sn   = $request->input('order_sn');
        $order_info = $this->planeOrderRepo->getOrderInfo($order_sn);

        if (!$order_info || !Gate::allows('order-access', $order_info)) {
            return $this->error(404, "订单不存在");
        }
        $change_param = $request->all();
        $bm           = new BookOrdersManager($change_param);
        $orders       = $bm->plane_change();
        /**
         * @var PlaneOrder $o
         */
        $o = $orders['order_info'];
        Log::info(json_encode(['method' => '飞机改签', 'request' => $change_param], JSON_UNESCAPED_UNICODE));
        $order_info        = new PlaneOrderResource($this->planeOrderRepo->getOrderShowInfo($orders['order_info']->getOrderSn()));
        $origin_order_info = new PlaneOrderResource($this->planeOrderRepo->getOrderShowInfo($orders['origin_order_info']->getOrderSn()));
        $price_details     = new PriceDetailsResource($orders['price_details']);
        $pay_amount        = $o->getOrderAmount();
        $need_pay          = $pay_amount ? 1 : 0;

        return $this->success('', compact('need_pay', 'pay_amount', 'order_info', 'origin_order_info', 'price_details'));
    }
}
